home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / prog / asm_0_m.arj / FLASHDOS.ASM < prev    next >
Assembly Source File  |  1989-07-29  |  80KB  |  2,715 lines

  1. ;*-------------------------------------------------------------------*;
  2. ;* FlashDOS Version 2.1 by P.E.Colla 1988 - COLLA @ MARVM1           *;
  3. ;*                                                                   *;
  4. ;* This program start a secondary DOS command processor from         *;
  5. ;* inside applications.                                              *;
  6. ;*                                                                   *;
  7. ;* Version 2.0 10-Jul-89 Virtual memory support added.               *;
  8. ;* Version 2.1 25-Jul-89 Huge mode added.                            *;
  9. ;*                                                                   *;
  10. ;*-------------------------------------------------------------------*;
  11.  
  12.  
  13. ;*-------------------------------------------------------------------*;
  14. ;* DOS Memory Control Block - Chain Record Format (Undocumented)     *;
  15. ;*-------------------------------------------------------------------*;
  16.  
  17. mem      segment  at      0FFFFh
  18.  
  19. memtype           db      ?
  20. memid             dw      ?
  21. memsize           dw      ?
  22.  
  23. mem      ends
  24.  
  25. ;*-------------------------------------------------------------------*;
  26. ;* Main Program Start                                                *;
  27. ;*-------------------------------------------------------------------*;
  28. cseg     segment  para    public 'code'
  29.                   org     100h
  30.                   assume  cs:cseg,ds:cseg,es:cseg,ss:cseg
  31. ;*-------------------------------------------------------------------*;
  32. ;* Equates                                                           *;
  33. ;*-------------------------------------------------------------------*;
  34.  
  35. cr                equ     0dh
  36. lf                equ     0ah
  37. bell              equ     07h
  38. hotkey            equ     0Eh
  39. shift_mask        equ     08h
  40. ncol              equ     80
  41. box_row           equ     0
  42. box_col           equ     0
  43. bw_attr           equ     70h
  44. co_attr           equ     17h
  45. id_len            equ     (id_end - id) - 1
  46. prog_len          equ     (initialize - main) / 10h
  47. env_var_len       equ     (env_var_end - env_var)
  48. video_len         equ     315
  49.  
  50. ;*-------------------------------------------------------------------*;
  51. ;* Control is given here at load time, jump to initialization code   *;
  52. ;*-------------------------------------------------------------------*;
  53.  
  54. main:             jmp     initialize
  55.  
  56. ;*-------------------------------------------------------------------*;
  57. ;* Variable definition area                                          *;
  58. ;*-------------------------------------------------------------------*;
  59. ;***----                 COMMON AREA                            ---***;
  60.  
  61. ;*--- Unique ID to detect multiple load
  62.  
  63. id                db      "@#PonchiFlashDOS#@"
  64. id_unique         db      10 dup (0)
  65. id_end            db      0
  66.  
  67. ;*--- External Swap File Area
  68.  
  69. swapfile          db      "A:\FLASHDOS.SWP",0
  70. handle            dw      ?
  71.  
  72. ;*--- Inter-Process Communication
  73.  
  74. rc                db      00h
  75.  
  76. ;*--- DOS command to be passed to COMMAND.COM at start
  77.  
  78. dos_command_def   db      3,"  ",cr,0,0
  79. dos_command       db      0,40 dup (" "),cr,0,0
  80. command_flag      db      0
  81.  
  82. ;*--- Status control area
  83.  
  84. active            db      0
  85. dormant           db      0
  86. buffer_type       db      "I"
  87. huge_mode         db      0
  88.  
  89. ;*--- WorkSpace Address & Size
  90.  
  91. ptr_area          dw      0
  92. size_area         dw      4096
  93.  
  94. ;*--- Runtime error & messages
  95.  
  96. merr01            db      cr,lf
  97.                   db      "FlashDOS: Invalid Function Code",cr,lf,"$"
  98. merr02            db      cr,lf
  99.                   db      "FlashDOS: File not found",cr,lf,"$"
  100. merr05            db      cr,lf
  101.                   db      "FlashDOS: Access Denied",cr,lf,"$"
  102. merr07            db      cr,lf
  103.                   db      "FlashDOS: Memory Blocks Destroyed",cr,lf,"$"
  104. merr08            db      cr,lf
  105.                   db      "FlashDOS: Insufficient memory",cr,lf,"$"
  106. merr09            db      cr,lf
  107.                   db      "FlashDOS: Invalid Memory Block Address",cr,lf,"$"
  108. merr10            db      cr,lf
  109.                   db      "FlashDOS: Invalid Media",cr,lf,"$"
  110. merr11            db      cr,lf
  111.                   db      "FlashDOS: Invalid Format",cr,lf,"$"
  112. merrff            db      cr,lf
  113.                   db      "FlashDOS: Protection Exception",cr,lf,"$"
  114. merrot            db      cr,lf
  115.                   db      "FlashDOS: Something wrong occurs",cr,lf,"$"
  116. now_inactive      db      cr,lf
  117.                   db      "FlashDOS: Now Inactive",cr,lf,"$"
  118. StartUp           db      cr,lf
  119. db "╔═════════════════════════════════════════════════════════════════════════════╗",cr,lf
  120. db "║             FlashDOS Version 2.1  by P.E.Colla (COLLA @ MARVM1)             ║",cr,lf
  121. db "║                              Type EXIT to End                           "
  122. type_msg          db      "Real"
  123.                   db       "║",cr,lf
  124. db "╚═════════════════════════════════════════════════════════════════════════════╝",cr,lf
  125.                   db      "$"
  126. disk_msg          db      "Disk"
  127. huge_msg          db      "Huge"
  128. SwapMsg           db      cr,lf
  129.                   db "╔═════════════════════════════════╗",cr,lf
  130.                   db "║          FlashDOS V2.1          ║",cr,lf
  131.                   db "║Swapping to Drive "
  132. Drive             db "A:"
  133.                   db ", Please wait║",cr,lf
  134.                   db "╚═════════════════════════════════╝",cr,lf
  135.                   db      "$"
  136. db "                                                                              ",cr,lf
  137.  
  138. Finish            db      cr,lf
  139.                   db      "FlashDOS Ended",cr,lf,"$"
  140. dos_error         db      cr,lf
  141.                   db      "FlashDOS: Secondary COMMAND cann't start",cr,lf,"$"
  142. claim_error       db      cr,lf
  143.                   db      "FlashDOS: Cann't claim memory",cr,lf,"$"
  144.  
  145. ;*--- Errors associated with swap process
  146.  
  147. emem_error        db      cr,lf
  148.                   db      "FlashDOS: Memory mgmt error",cr,lf,"$"
  149. epsp_error        db      cr,lf
  150.                   db      "FlashDOS: PSP do not belong to Usr Program",cr,lf,"$"
  151. edisk_error       db      cr,lf
  152.                   db      "FlashDOS: Disk error, Can not swap out",cr,lf,"$"
  153. eno_space         db      cr,lf
  154.                   db      "╔════════════════════════════════╗",cr,lf
  155.                   db      "║          FlashDOS 2.0          ║",cr,lf
  156.                   db      "║    Not enough space to swap    ║",cr,lf
  157.                   db      "║   Press any key to continue    ║",cr,lf
  158.                   db      "╚════════════════════════════════╝",cr,lf,"$"
  159. eusr_short        db      cr,lf
  160.                   db      "╔════════════════════════════════╗",cr,lf
  161.                   db      "║          FlashDOS 2.0          ║",cr,lf
  162.                   db      "║    Insufficient User Memory    ║",cr,lf
  163.                   db      "║   Press any key to continue    ║",cr,lf
  164.                   db      "╚════════════════════════════════╝",cr,lf,"$"
  165. eno_open          db      cr,lf
  166.                   db      "FlashDOS: Can not open swap file",cr,lf,"$"
  167. eno_swap          db      cr,lf
  168.                   db      "FlashDOS: Can not swap to file",cr,lf,"$"
  169. eno_shrink        db      cr,lf
  170.                   db      "FlashDOS: Can not shrink Usr memory",cr,lf,"$"
  171. eswap_ok          db      cr,lf
  172.                   db      "FlashDOS: User program swapped OK",cr,lf,"$"
  173. eno_retrieve      db      cr,lf
  174.                   db      "FlashDOS: Can not retrieve memory",cr,lf,"$"
  175. eno_close         db      cr,lf
  176.                   db      "FlashDOS: Can not close swap file",cr,lf,"$"
  177. eno_erase         db      cr,lf
  178.                   db      "FlashDOS: Can not erase swap file",cr,lf,"$"
  179.  
  180.  
  181. ;*--- Local Stack Definition
  182.  
  183. Old_ss            dw   ?
  184. Old_sp            dw   ?
  185. Free_Space        dw   512  dup (?)
  186. Loc_sp            dw   10   dup (?)
  187.  
  188. ;*--- Interrupt saving area
  189.  
  190. Old_Int_Area      dw   1200 dup (?)
  191. New_Int_Area      dw   1200 dup (?)
  192.  
  193. ;*--- EXEC control block
  194.  
  195. env_segment       dw      ?
  196. command_ptr       dw      2 dup (?)
  197. fcb1_ptr          dw      2 dup (?)
  198. fcb2_ptr          dw      2 dup (?)
  199.  
  200. ;*--- COMMAND.COM path
  201.  
  202. comspec_path      db      "A:\COMMAND.COM",0
  203.                   db      100 dup (0)
  204. env_var           db      "COMSPEC="
  205. env_var_end       db      ?
  206.  
  207.  
  208. ;*--- User memory block information
  209.  
  210. usr_base          dw      ?
  211. usr_psp           dw      ?
  212. usr_size          dw      ?
  213. usr_last          dw      ?
  214.  
  215. ;*--- Swap process auxiliary registers
  216.  
  217. swp_len           dw      ?
  218. swp_par           dw      ?
  219. usr_ptr           dw      ?
  220. usr_len           dw      ?
  221.  
  222. ;*--- Stack save area
  223.  
  224. ss_save           dw      ?
  225. sp_save           dw      ?
  226.  
  227. ;*--- Old Interrupt Address
  228.  
  229. old_int_9         dd      0
  230. old_int_13        dd      0
  231. old_int_21        dd      0
  232.  
  233. ;*--- Video Information
  234.  
  235. cursor_pos        dw      0
  236. display_page      db      0
  237. attribute         db      0
  238. nrow              db      25
  239.  
  240. ;*--- Flags & Status
  241.  
  242. disk_status       db      0
  243. load_flag         db      0
  244. dos_flag          dd      0
  245. info_ptr          dd      00000487h
  246. lo_fn_flag        db      0
  247. paragraph_size    db      10h
  248. par_size          dw      10h
  249.  
  250.  
  251. ;*-------------------------------------------------------------------*;
  252. ;* New BIOS Keyboard Interrupt                                       *;
  253. ;*-------------------------------------------------------------------*;
  254.  
  255. int_9             proc    far
  256.                   assume  cs:cseg,ds:nothing,es:nothing,ss:nothing
  257.  
  258. ;*--- Check if Hot Key is pressed
  259.  
  260.                   sti
  261.                   push    ax
  262.                   mov     ah,0ffh
  263.                   mov     cs:rc,ah
  264.                   in      al,60h
  265.                   cmp     al,hotkey
  266.                   jne     process_key
  267.                   mov     ah,2
  268.                   int     16h
  269.                   and     al,0Fh
  270.                   cmp     al,shift_mask
  271.                   je      our_key
  272.  
  273. ;*--- No, continue with old keyboard interrupt handler
  274.  
  275. process_key:
  276.                   pop     ax
  277.                   jmp     dword ptr cs:old_int_9
  278.  
  279. ;*--- Yes,reset keyboard and see if it is possible to pop up
  280.  
  281. our_key:
  282.                   in      al,61h
  283.                   mov     ah,al
  284.                   or      al,80h
  285.                   out     61h,al
  286.                   jmp     short $+2
  287.                   out     61h,al
  288.                   cli
  289.                   mov     al,20h
  290.                   out     20h,al
  291.                   sti
  292.  
  293. ;*--- Is FlashDOS already active
  294.  
  295.                   cmp     cs:active,0
  296.                   jne     return_a
  297.  
  298. ;*--- Is DOS in critical state
  299.  
  300.                   push    ds
  301.                   push    bx
  302.                   lds     bx,cs:dos_flag
  303.                   cmp     byte ptr [bx],0
  304.                   jne     return_b
  305.  
  306. ;*--- Is DOS performing Int 21h greather than 0Ch
  307.  
  308.                   cmp     cs:lo_fn_flag,0
  309.                   jne     return_b
  310.  
  311. ;*--- Is any disk activity in progress
  312.  
  313. check_b:          cmp     cs:disk_status,0
  314.                   jne     return_b
  315.  
  316. ;*--- Is active
  317.  
  318.                   cmp     cs:dormant,0
  319.                   je      invoke
  320.  
  321. return_b:         pop     bx
  322.                   pop     ds
  323. return_a:         pop     ax
  324.                   iret
  325.  
  326. ;*--- Condition OK to popup, video condition is saved
  327.  
  328. invoke:           lds     bx,cs:info_ptr
  329.                   lds     bx,[bx]
  330.                   test    bl,08h
  331.                   jnz     return_b
  332.                   mov     attribute,co_attr
  333.                   mov     ah,0Fh
  334.                   int     10h
  335.                   mov     display_page,bh
  336.                   cmp     al,3
  337.                   jbe     mode_ok
  338.                   mov     attribute,bw_attr
  339.                   cmp     al,7
  340.                   jne     return_b
  341.  
  342. ;*--- Set active flag, FlashDOS is not re-entrant.
  343.  
  344. mode_ok:          inc     cs:active
  345.  
  346. ;*--- Signal with interprocess purposes that at least the condition for popup
  347. ;*--- was completed
  348.  
  349.                   mov     ah,80h
  350.                   mov     cs:rc,ah
  351.  
  352. ;*--- Put the stack on a safe place and Save everything
  353.  
  354.                   cli
  355.  
  356.                   mov    cs:old_ss,ss
  357.                   mov    cs:old_sp,sp
  358.                   push   cs
  359.                   pop    ss
  360.                   mov    sp,offset cs:Loc_sp
  361.  
  362.                   sti
  363.  
  364.                   push    cx
  365.                   push    dx
  366.                   push    di
  367.                   push    si
  368.                   push    es
  369.                   push    bp
  370.  
  371.                   push    cs
  372.                   pop     ds
  373.  
  374.                   push    cs
  375.                   pop     es
  376.  
  377. ;*--- IF External swap mode then preserve interrupt vector and restore the
  378. ;*--- vector that was at the FlashDos loading time.
  379. ;*--- This operation avoid any conflict if the current program have one or
  380. ;*--- more interrupt vectors trapped (pointing to nowhere if swapped).
  381.  
  382.                   cmp     cs:buffer_type,"E"
  383.                   jne     txintend
  384.  
  385.                   cli
  386.  
  387.                   push    es
  388.  
  389.                   mov     ax,0000h
  390.                   mov     es,ax
  391.  
  392.  
  393.                   mov     si,0000h
  394.                   lea     di,new_int_area
  395.                   mov     bx,1024
  396.  
  397. txintold:
  398.                   mov     ah,byte ptr es:[si]
  399.                   mov     byte ptr cs:[di],ah
  400.                   inc     di
  401.                   inc     si
  402.                   dec     bx
  403.  
  404.                   mov     ax,bx
  405.                   cmp     ax,0000h
  406.                   jne     txintold
  407.  
  408.                   mov     si,0000h
  409.                   lea     di,old_int_area
  410.                   mov     bx,1024
  411.  
  412. txintnew:
  413.                   mov     ah,byte ptr cs:[di]
  414.                   mov     byte ptr es:[si],ah
  415.                   inc     di
  416.                   inc     si
  417.                   dec     bx
  418.  
  419.                   mov     ax,bx
  420.                   cmp     ax,0000h
  421.                   jne     txintnew
  422.  
  423.                   pop     es
  424.  
  425.                   sti
  426.  
  427. txintend:
  428.  
  429.                   assume  ds:cseg,es:cseg
  430.  
  431.                   mov     ax,cs
  432.                   mov     ds,ax
  433.                   mov     es,ax
  434.                   mov     ah,3
  435.                   int     10h
  436.                   mov     cursor_pos,dx
  437.  
  438. ;*--- Save & clear screen
  439.  
  440.                   mov     di,offset initialize
  441.                   mov     si,0FFFFh
  442.                   call    screen
  443.  
  444. ;*--- If a user program is selected to popup don't clear the screen
  445.  
  446.                   cmp     byte ptr cs:command_flag,00h
  447.                   jne     dos_ldr
  448.  
  449. ;*--- If external swap is specified don't clear the screen neither
  450.  
  451.                   cmp     byte ptr cs:buffer_type,"E"
  452.                   je      dos_ldr
  453.  
  454.                   call    clr_box
  455.  
  456. ;*--- Try to load COMMAND.COM
  457. dos_ldr:
  458.                   call    dos_loader
  459.  
  460. ;*--- Restore screen
  461.  
  462.                   mov     si,offset initialize
  463.                   call    screen
  464.                   mov     ah,2
  465.                   mov     dx,cursor_pos
  466.                   int     10h
  467.  
  468. ;*--- Reset active flag
  469.  
  470.                   mov     active,0
  471.  
  472. ;*--- Restore registers
  473.  
  474.                   pop     bp
  475.                   pop     es
  476.                   pop     si
  477.                   pop     di
  478.                   pop     dx
  479.                   pop     cx
  480.  
  481. ;*--- Restore Stack
  482.  
  483.                   cli
  484.  
  485.                   mov    ss,old_ss
  486.                   mov    sp,old_sp
  487.  
  488.                   sti
  489.  
  490. ;*--- Check if storage mode is external or internal
  491. ;*--- If External restore Interrupt Vector area
  492.  
  493.                   cmp     cs:buffer_type,"E"
  494.                   jne     endint9
  495.  
  496.                   cli
  497.  
  498.                   push    es
  499.  
  500.                   mov     ax,0000h
  501.                   mov     es,ax
  502.  
  503.                   mov     si,0000h
  504.                   lea     di,new_int_area
  505.                   mov     bx,1024
  506.  
  507. reintold:
  508.                   mov     ah,byte ptr cs:[di]
  509.                   mov     byte ptr es:[si],ah
  510.                   inc     di
  511.                   inc     si
  512.                   dec     bx
  513.  
  514.                   mov     ax,bx
  515.                   cmp     ax,0000h
  516.                   jne     reintold
  517.  
  518.                   pop     es
  519.                   sti
  520.  
  521. ;*--- Signal with inter-process purposes that the program sucefully ended
  522.  
  523.                   mov     ah,00h
  524.                   mov     cs:rc,ah
  525.  
  526. endint9:
  527.                   pop     bx
  528.                   pop     ds
  529.                   pop     ax
  530.  
  531.  
  532.                   iret
  533. int_9             endp
  534.  
  535.  
  536. ;*-------------------------------------------------------------------*;
  537. ;* Loader of secondary COMMAND.COM                                   *;
  538. ;*-------------------------------------------------------------------*;
  539. dos_loader        proc    near
  540.  
  541. ;*--- Set addresability
  542.  
  543.                   mov     ax,cs
  544.                   mov     ds,ax
  545.                   mov     es,ax
  546.  
  547. ;*--- Get current video page
  548.  
  549.                   mov     ah,0Fh
  550.                   Int     10h
  551.  
  552. ;*--- Position cursor at upper left corner (0,0)
  553.  
  554.                   mov     bl,00h
  555.                   mov     dx,0000h
  556.                   mov     ah,02h
  557.                   Int     10h
  558.  
  559. ;*--- Check if Internal or External swap is selected
  560.  
  561.                   cmp     cs:buffer_type,"E"
  562.                   je      external_swap
  563.  
  564. ;*--- Get pointer to workspace area (If internal swap is active)
  565.  
  566. internal_storage:
  567.                   mov     ax,word ptr cs:ptr_area
  568.  
  569. ;*--- Freed up reserved workspace area
  570.  
  571.                   mov     es,ax
  572.                   mov     ah,49h
  573.                   Int     21h
  574.  
  575. ;*--- OK, go to load command.com
  576.  
  577.                   jc      intsto01
  578.                   jmp     load_command
  579.  
  580. ;*--- Display error message (never should happen)
  581.  
  582. intsto01:
  583.                   mov     dx,offset claim_error
  584.                   call    print
  585.  
  586.                   jmp     escape
  587.  
  588. ;*--- External Swap procedure
  589.  
  590. external_swap:
  591.  
  592. ;*--- Get current (user program) PSP segment
  593.  
  594.                   mov     ah,62h
  595.                   Int     21h
  596.  
  597.                   mov     cs:usr_psp,bx
  598.  
  599.  
  600. ;*--- Based on PSP segment address the User's MCB is accesed
  601.  
  602.                   push    ds
  603.  
  604.                   mov     ax,cs:usr_psp
  605.                   dec     ax
  606.                   mov     ds,ax
  607.  
  608.                   assume  ds:mem
  609.  
  610. ;*--- Verify is the MCB is one of the expected type
  611.  
  612.  
  613.                   cmp     ds:memtype,"M"
  614.                   je      eswap01
  615.  
  616.                   cmp     ds:memtype,"Z"
  617.                   je      eswap01
  618.  
  619.                   mov     dx,offset emem_error
  620.                   call    print
  621.                   call    getkey
  622.                   pop     ds
  623.                   jmp     escape
  624.  
  625. ;*--- Get the owner of the MCB (Should be the PSP just retrieved above)
  626.  
  627. eswap01:
  628.                   mov     ax,cs:usr_psp
  629.                   cmp     ds:memid,ax
  630.                   je      eswap02
  631.  
  632.                   mov     dx,offset epsp_error
  633.                   call    print
  634.                   call    getkey
  635.                   pop     ds
  636.                   jmp     escape
  637.  
  638. ;*--- Get the memory size of the block owned by the PSP (in paragraphs)
  639.  
  640. eswap02:
  641.                   mov     ax,ds:memsize
  642.                   mov     cs:usr_size,ax
  643.  
  644. ;*--- If huge mode is in place the swappable area is set to the user size
  645. ;*--- minus one.
  646.                   cmp     byte ptr cs:huge_mode,01h
  647.                   jnz     eswap02b
  648.  
  649. ;*--- The reason to let at least one user block in memory is really to avoid
  650. ;*--- the mess to completely erase the user MCB and after the operation
  651. ;*--- restore it.
  652.                   mov     ax,word ptr cs:usr_size
  653.                   sub     ax,10h
  654.                   mov     word ptr cs:size_area,ax
  655.  
  656.                   assume  ds:cseg
  657.  
  658. eswap02b:
  659.                   pop     ds
  660.  
  661. ;*--- The User PSP size is checked against the size of the area required
  662.  
  663.                   cmp     ax,size_area
  664.                   jnb     eswap09
  665.  
  666.                   mov     dx,offset eusr_short
  667.                   call    print
  668.                   call    getkey
  669.                   jmp     escape
  670.  
  671. ;*--- The actual segment from wich the memory will be swapped to disk
  672. ;*--- is computed.
  673. ;*--- First, the last allocated paragraph is computed
  674.  
  675. eswap09:
  676.  
  677.                   mov     ax,cs:usr_psp
  678.                   dec     ax
  679.                   mov     bx,cs:usr_size
  680.                   add     ax,bx
  681.                   dec     ax
  682.                   mov     cs:usr_last,ax
  683.  
  684. ;*--- Now the paragraph in which the swap will start is computed
  685.  
  686.                   inc     ax
  687.                   sub     ax,cs:size_area
  688.                   mov     cs:usr_base,ax
  689.  
  690.  
  691. ;*--- All the memory dirty work is already done, now all the user's files
  692. ;*--- are closed (if any).
  693.  
  694.                   push    bx
  695.                   push    cx
  696.                   mov     cx,0Fh
  697.                   mov     bx,05h
  698.  
  699. eswap03:
  700.                   mov     ah,3Eh
  701.                   Int     21h
  702.  
  703.                   inc     bx
  704.                   loop    eswap03
  705.  
  706.                   pop     cx
  707.                   pop     bx
  708.  
  709.  
  710. ;*--- Now take a look around to found space enough to swap out the memory
  711. ;*--- Scan drive F: thru A:
  712.  
  713.                   mov     dl,05h
  714.                   mov     dh,00h
  715.  
  716. ;*--- Try to get disk status for the selected drive
  717.  
  718. eswap04:
  719.  
  720.                   clc
  721.  
  722.                   mov     di,dx
  723.                   mov     al,00h
  724.                   mov     ah,36h
  725.                   Int     21h
  726.  
  727.                   jnc     eswap05
  728.  
  729.                   mov     dx,offset edisk_error
  730.                   call    print
  731.                   call    getkey
  732.                   jmp     escape
  733.  
  734. ;*--- If AX=FFFFh there are no drive available to check
  735.  
  736. eswap05:
  737.  
  738.                   cmp     ax,0FFFFh
  739.                   jne     eswap06
  740.  
  741. ;*--- Decrement drive to next available and check again
  742.  
  743. eswap08:
  744.                   mov     dx,di
  745.                   dec     dl
  746.                   jnz     eswap04
  747.  
  748. ;*--- If drive count reach 0 no one of the drive have enough space to swap
  749.  
  750.                   mov     dx,offset eno_space
  751.                   call    print
  752.                   call    getkey
  753.                   jmp     escape
  754.  
  755. eswap06:
  756.  
  757. ;*--- Check if the space available is really huge, otherwise a
  758. ;*--- free amount of paragraphs could be greater than FFFFh and
  759. ;*--- the space computation could end on error
  760.  
  761.                   push    ax
  762.                   mov     ax,bx
  763.                   cmp     ax,1000
  764.                   jge     eswap16
  765.                   jmp     eswap17
  766.  
  767. eswap16:
  768.                   pop     ax
  769.                   jmp     eswap07
  770.  
  771. ;*--- Get free space on drive
  772. ;*--- First get bytes on each cluster
  773.  
  774. eswap17:
  775.                   pop     ax
  776.                   mul     cx
  777.  
  778.  
  779. ;*--- Then convert to paragraphs by cluster
  780.  
  781.                   idiv    paragraph_size
  782.  
  783.                   mov     ah,00h
  784.  
  785. ;*--- Now get total number of paragraphs available on drive
  786.  
  787.                   mul     bx
  788.  
  789. ;*--- Compare with amount needed, if not enough continue to cycle
  790.  
  791.                   cmp     ax,size_area
  792.                   jnb     eswap07
  793.                   jmp     eswap08
  794.  
  795. eswap07:
  796.  
  797. ;*--- Now the drive with sufficient space is on DI, transfer to DX
  798.  
  799.                   mov     dx,di
  800.  
  801. ;*--- Convert the drive number to a useful form
  802.  
  803.                   add     dl,40h
  804.                   mov     cs:swapfile,dl
  805.                   mov     cs:drive,dl
  806.  
  807. ;*--- Print swap in progress message
  808.  
  809.                   mov     ax,cs
  810.                   mov     ds,ax
  811.                   mov     dx,offset SwapMsg
  812.                   call    print
  813.  
  814. ;*--- Create and open the swapfile (hidden file)
  815.  
  816.                   push    cs
  817.                   pop     ds
  818.                   mov     dx,offset swapfile
  819.                   mov     cx,02h
  820.                   mov     ah,03cH
  821.                   Int     21h
  822.  
  823.                   jnc     eswap10
  824.  
  825.                   mov     dx,offset eno_open
  826.                   call    print
  827.                   call    getkey
  828.                   jmp     escape
  829.  
  830. ;*--- Store the handle number returned by DOS
  831.  
  832. eswap10:
  833.                   mov     cs:handle,ax
  834.  
  835. ;*--- Now the swap is actually done
  836. ;*--- Set the address FROM
  837.  
  838.                   mov     ax,cs:usr_base
  839.                   mov     cs:usr_ptr,ax
  840.  
  841. ;*--- Set the size to swap
  842.  
  843.                   mov     ax,size_area
  844.                   mov     usr_len,ax
  845.  
  846. ;*--- Cycle thru the swapable area swapping on 64K chunks
  847.  
  848. eswap11:
  849.                   mov     bx,usr_len
  850.                   mov     ax,0fffh
  851.  
  852.                   cmp     ax,bx
  853.                   jb      more_64K
  854.  
  855.                   mov     ax,usr_len
  856.                   mul     par_size
  857.                   mov     swp_len,ax
  858.                   mov     swp_par,bx
  859.                   jmp     swap_in
  860.  
  861. more_64K:
  862.                   mov     ax,0FFF0h
  863.                   mov     swp_len,ax
  864.                   mov     ax,0fffh
  865.                   mov     swp_par,ax
  866. swap_in:
  867.                   clc
  868.                   mov     bx,handle
  869.                   mov     cx,swp_len
  870.                   mov     dx,0000h
  871.                   push    ds
  872.                   mov     ax,usr_ptr
  873.                   mov     ds,ax
  874.                   mov     ah,40h
  875.                   mov     al,00h
  876.                   Int     21h
  877.                   pop     ds
  878.  
  879.                   jnc     eswap12
  880.  
  881. ;*--- Check if the amount of bytes wrote is equal than expected
  882.  
  883.                   mov     dx,offset eno_swap
  884.                   call    print
  885.                   call    getkey
  886.                   jmp     escape
  887.  
  888. ;*--- Increment pointer (next paragraph) decrement remaining size
  889.  
  890. eswap12:
  891.  
  892.                   mov     ax,usr_ptr
  893.                   add     ax,swp_par
  894.                   mov     usr_ptr,ax
  895.  
  896.                   mov     ax,usr_len
  897.                   sub     ax,swp_par
  898.                   mov     usr_len,ax
  899.  
  900.  
  901. ;*--- When remainder is equal to zero the swap is finished
  902.  
  903.                   cmp     ax,0000h
  904.                   jne     eswap11
  905.  
  906.                   cmp     byte ptr cs:command_flag,00h
  907.                   jne     eswap18
  908.  
  909. ;*--- Clear Screen & Position cursor at upper left corner (0,0)
  910.  
  911.                   push    ds
  912.                   push    es
  913.                   call    clr_box
  914.  
  915.                   mov     bl,00h
  916.                   mov     dx,0000h
  917.                   mov     ah,02h
  918.                   Int     10h
  919.                   pop     es
  920.                   pop     ds
  921.  
  922. ;*--- To complete the swap the swapfile is closed
  923.  
  924. eswap18:
  925.                   clc
  926.  
  927.                   mov     bx,cs:handle
  928.                   mov     ah,3Eh
  929.                   Int     21h
  930.  
  931.                   jnc     eswap15
  932.  
  933.                   mov     dx,offset eno_close
  934.                   call    print
  935.                   call    getkey
  936.                   jmp     escape
  937.  
  938. ;*--- When the swap is complete the piece of the user program swaped is
  939. ;*--- shrinked down to allow free space to be used.
  940.  
  941. eswap15:
  942.  
  943.                   mov     ax,usr_size
  944.                   sub     ax,size_area
  945.                   mov     bx,ax
  946.                   mov     ax,usr_psp
  947.                   mov     es,ax
  948.                   mov     ah,4ah
  949.                   mov     al,00h
  950.                   Int     21h
  951.  
  952.                   jnc     load_command
  953.  
  954.                   mov     dx,offset eno_shrink
  955.                   call    print
  956.                   call    getkey
  957.                   jmp     escape
  958.  
  959. load_command:
  960.  
  961. ;*--- Set contents of EXEC Control Block
  962.  
  963.                   mov     ax,word ptr cs:2Ch
  964.                   mov     env_segment,ax
  965.                   mov     word ptr cs:env_segment + 4,cs
  966.  
  967. ;*--- Select between default or specified DOS Command
  968.  
  969.                   cmp     command_flag,00h
  970.                   je      default_com
  971.                   mov     word ptr cs:env_segment + 2,offset dos_command
  972.                   jmp     start_load
  973.  
  974. default_com:
  975.  
  976.                   mov     word ptr cs:env_segment + 2,offset dos_command_def
  977.  
  978. ;*--- Save main registers on stack
  979.  
  980. start_load:
  981.                   push    es
  982.                   push    ds
  983.                   push    bp
  984.  
  985. ;*--- Save stack itself
  986.  
  987.                   mov     ss_save,ss
  988.                   mov     sp_save,sp
  989.  
  990. ;*--- Display PopUp message
  991.  
  992.                   cmp     byte ptr cs:command_flag,00h
  993.                   jne     cont_load
  994.  
  995.                   mov     ax,cs
  996.                   mov     ds,ax
  997.                   mov     dx,offset StartUp
  998.                   call    print
  999.  
  1000. ;*--- Load & Exec a Secondary DOS Command Processor
  1001. cont_load:
  1002.                   mov     ax,cs
  1003.                   mov     ds,ax
  1004.                   mov     es,ax
  1005.                   lea     dx,comspec_path
  1006.                   lea     bx,env_segment
  1007.                   mov     ah,4bh
  1008.                   mov     al,00h
  1009.                   Int     21h
  1010.  
  1011. ;*--- Restore stack & registers
  1012.  
  1013.                   mov     ss,ss_save
  1014.                   mov     sp,sp_save
  1015.  
  1016.                   pop     bp
  1017.                   pop     ds
  1018.                   pop     es
  1019.  
  1020. ;*--- Something wrong? , Display message.
  1021.  
  1022.                   jc      load_error
  1023.  
  1024. end_load:
  1025.                   cmp     byte ptr cs:command_flag,00h
  1026.                   jne     end_ldb
  1027.  
  1028. ;*--- Display End Session message
  1029.  
  1030.                   mov     dx,offset Finish
  1031.                   call    print
  1032.  
  1033. end_ldb:
  1034.  
  1035.                   cmp     cs:buffer_type,"E"
  1036.                   je      external_retrieve
  1037.  
  1038. ;*--- If internal swap done Allocate workspace again to preserve it.
  1039.  
  1040. internal_retrieve:
  1041.  
  1042.                   mov     ax,cs
  1043.                   mov     ds,ax
  1044.                   mov     es,ax
  1045.                   mov     bx,size_area
  1046.                   mov     ah,48h
  1047.                   Int     21h
  1048.  
  1049. ;*--- Cann't, display message.
  1050.  
  1051.                   jc      prt_mem_err
  1052.  
  1053. ;*--- Workspace is under ownership of the interrupted program
  1054. ;*--- Access DOS Memory Control Block of allocated space and change
  1055. ;*--- ID to point to PSP of FlashDOS.
  1056.  
  1057.                   mov     word ptr cs:ptr_area,ax
  1058.                   dec     ax
  1059.                   mov     ds,ax
  1060.  
  1061.                   assume  ds:mem
  1062.  
  1063.                   cmp     ds:memtype,"M"
  1064.                   jne     chg_mem_err
  1065.  
  1066.                   mov     ax,cs
  1067.                   mov     ds:memid,ax
  1068.  
  1069. ;*--- Restablish addresability
  1070.  
  1071.                   assume  cs:cseg,ds:cseg,es:cseg,ss:cseg
  1072.                   mov     ax,cs
  1073.                   mov     ds,ax
  1074.                   jmp     escape
  1075.  
  1076. ;*--- Error handling & display messages
  1077.  
  1078. chg_mem_err:
  1079.                   mov     ax,0ffh
  1080. prt_mem_err:
  1081.                   call    memory_error
  1082.  
  1083. ;*--- Cann't claim back its memory, became inactive
  1084.  
  1085.                   mov     dormant,01h
  1086.                   mov     dx,offset now_inactive
  1087.                   call    print
  1088.  
  1089.                   jmp     escape
  1090.  
  1091. ;*--- If load error is found after the message the workarea is claimed again
  1092.  
  1093. load_error:
  1094.                   call    memory_error
  1095.                   call    getkey
  1096.                   jmp     end_load
  1097.  
  1098. ;*--- If external retrieve is active the memory is swapped back
  1099.  
  1100. external_retrieve:
  1101.  
  1102. ;*--- Last, the Usr program is restored as a main PSP for DOS
  1103.  
  1104.                   push    cs
  1105.                   pop     ax
  1106.                   mov     es,ax
  1107.                   mov     ds,ax
  1108.  
  1109. ;*--- The user memory block is restored to his original size
  1110.  
  1111.                   clc
  1112.  
  1113.                   mov     ax,usr_size
  1114.                   mov     bx,ax
  1115.                   mov     ax,usr_psp
  1116.                   mov     es,ax
  1117.                   mov     ah,4ah
  1118.                   mov     al,00h
  1119.                   Int     21h
  1120.  
  1121.                   jnc     eretr01
  1122.  
  1123.                   mov     dx,offset eno_retrieve
  1124.                   call    print
  1125.                   call    getkey
  1126.                   jmp     escape
  1127.  
  1128. eretr01:
  1129.  
  1130. ;*--- Now the swapfile is open for read
  1131.  
  1132.                   clc
  1133.  
  1134.                   push    cs
  1135.                   pop     ds
  1136.                   mov     dx,offset swapfile
  1137.                   mov     ax,3D00h
  1138.                   Int     21h
  1139.  
  1140.                   jnc     eretr02
  1141.  
  1142.                   mov     dx,offset eno_open
  1143.                   call    print
  1144.                   call    getkey
  1145.                   jmp     escape
  1146.  
  1147. ;*--- If the file was sucefully open the swaped part of the memory is restored
  1148.  
  1149. eretr02:
  1150.                   mov     cs:handle,ax
  1151.  
  1152.                   push    cs
  1153.                   pop     ax
  1154.                   mov     es,ax
  1155.                   mov     ds,ax
  1156.  
  1157.                   mov     ax,usr_base
  1158.                   mov     usr_ptr,ax
  1159.                   mov     ax,size_area
  1160.                   mov     usr_len,ax
  1161.  
  1162. eretr03:
  1163.                   mov     bx,usr_len
  1164.                   mov     ax,0fffh
  1165.  
  1166.  
  1167.                   cmp     ax,bx
  1168.                   jb      more_64Kb
  1169.  
  1170.                   mov     ax,usr_len
  1171.                   mul     par_size
  1172.                   mov     swp_len,ax
  1173.                   mov     swp_par,bx
  1174.                   jmp     swap_out
  1175.  
  1176. more_64Kb:
  1177.                   mov     ax,0FFF0h
  1178.                   mov     swp_len,ax
  1179.                   mov     ax,0fffh
  1180.                   mov     swp_par,ax
  1181.  
  1182. swap_out:
  1183.                   clc
  1184.  
  1185.                   mov     bx,handle
  1186.                   mov     cx,swp_len
  1187.                   mov     dx,0000h
  1188.  
  1189.                   push    ds
  1190.                   mov     ax,usr_ptr
  1191.                   mov     ds,ax
  1192.                   mov     al,00h
  1193.                   mov     ah,3Fh
  1194.                   Int     21h
  1195.                   pop     ds
  1196.  
  1197.                   jnc     eretr04
  1198.  
  1199.                   mov     dx,offset eno_swap
  1200.                   call    print
  1201.                   call    getkey
  1202.                   jmp     escape
  1203.  
  1204. eretr04:
  1205.  
  1206.                   mov     ax,usr_ptr
  1207.                   add     ax,swp_par
  1208.                   mov     usr_ptr,ax
  1209.  
  1210.                   mov     ax,usr_len
  1211.                   sub     ax,swp_par
  1212.                   mov     usr_len,ax
  1213.  
  1214.                   cmp     ax,0000h
  1215.                   je      eretr04b
  1216.                   jmp     eretr03
  1217.  
  1218. ;*--- If the swap back ends sucefully the swapfile is closed
  1219.  
  1220. eretr04b:
  1221.                   mov     bx,handle
  1222.                   mov     ah,3Eh
  1223.                   Int     21h
  1224.  
  1225.                   jnc     eretr05
  1226.  
  1227.                   mov     dx,offset eno_close
  1228.                   call    print
  1229.                   call    getkey
  1230.                   jmp     escape
  1231.  
  1232. eretr05:
  1233.  
  1234. ;*--- Just to be clean the swapfile is erased from the disk
  1235.  
  1236.                   clc
  1237.  
  1238.                   push    cs
  1239.                   pop     ds
  1240.                   mov     dx,offset swapfile
  1241.                   mov     ah,41h
  1242.                   Int     21h
  1243.  
  1244.                   jnc     escape
  1245.  
  1246.                   mov     dx,offset eno_erase
  1247.                   call    print
  1248.                   call    getkey
  1249.                   jmp     escape
  1250.  
  1251. escape:
  1252.                   ret
  1253.  
  1254. dos_loader        endp
  1255.  
  1256. ;*-------------------------------------------------------------------*;
  1257. ;* Wait for any key to be pressed                                    *;
  1258. ;*-------------------------------------------------------------------*;
  1259.  
  1260. getkey            proc    near
  1261.  
  1262.                   mov     ah,1
  1263.                   int     16h
  1264.                   jne     getkey1
  1265.                   jmp     getkey
  1266.  
  1267. getkey1:          mov     ah,0
  1268.                   int     16h
  1269.  
  1270.                   ret
  1271. getkey            endp
  1272.  
  1273.  
  1274. ;*-------------------------------------------------------------------*;
  1275. ;* Save/Restore Screen                                               *;
  1276. ;*-------------------------------------------------------------------*;
  1277.  
  1278. screen            proc    near
  1279.                   cld
  1280.                   mov     bh,display_page
  1281.                   mov     ch,00
  1282.                   mov     cl,nrow
  1283.                   mov     dh,box_row
  1284. row_loop:
  1285.                   push    cx
  1286.                   mov     cx,ncol
  1287.                   mov     dl,box_col
  1288. col_loop:
  1289.                   push    cx
  1290.                   mov     ah,2
  1291.                   int     10h
  1292.                   cmp     si,0FFFFh
  1293.                   je      do_save
  1294.                   lodsw
  1295.                   mov     bl,ah
  1296.                   mov     ah,9
  1297.                   mov     cx,01
  1298.                   int     10h
  1299.                   jmp     short do_loop
  1300. do_save:
  1301.                   mov     ah,8
  1302.                   int     10h
  1303.                   stosw
  1304.  
  1305. do_loop:
  1306.                   inc     dl
  1307.                   pop     cx
  1308.                   loop    col_loop
  1309.                   pop     cx
  1310.                   inc     dh
  1311.                   loop    row_loop
  1312.                   ret
  1313. screen            endp
  1314.  
  1315.  
  1316. ;*-------------------------------------------------------------------*;
  1317. ;* Clear Screen and Set Color                                        *;
  1318. ;*-------------------------------------------------------------------*;
  1319.  
  1320. clr_box           proc    near
  1321.                   mov     ax,0600h
  1322.                   mov     ch,box_row
  1323.                   mov     cl,box_col
  1324.                   mov     dh,box_row - 1
  1325.                   add     dh,nrow
  1326.                   mov     dl,box_col + ncol - 1
  1327.                   mov     bh,attribute
  1328.                   int     10h
  1329.                   ret
  1330. clr_box           endp
  1331.  
  1332. ;*-------------------------------------------------------------------*;
  1333. ;* New Disk BIOS Interrupt Handler                                   *;
  1334. ;*-------------------------------------------------------------------*;
  1335.  
  1336. int_13            proc    far
  1337.                   assume  ds:nothing,es:nothing
  1338.                   mov     cs:disk_status,1
  1339.                   pushf
  1340.                   call    dword ptr cs:old_int_13
  1341.                   mov     cs:disk_status,0
  1342.                   sti
  1343.                   ret     2
  1344. int_13            endp
  1345.  
  1346. ;*-------------------------------------------------------------------*;
  1347. ;* New Main DOS Interrupt Handler                                    *;
  1348. ;*-------------------------------------------------------------------*;
  1349.  
  1350. int_21            proc    far
  1351.                   mov     cs:lo_fn_flag,0
  1352.                   cmp     ah,0
  1353.                   jne     check
  1354.                   mov     ah,4Ch
  1355. go_direct:
  1356.                   jmp     dword ptr cs:old_int_21
  1357. check:
  1358.                   cmp     ah,0ch
  1359.                   ja      go_direct
  1360.                   inc     cs:lo_fn_flag
  1361.                   pushf
  1362.                   call    dword ptr cs:old_int_21
  1363.                   mov     cs:lo_fn_flag,0
  1364.                   ret     2
  1365. int_21            endp
  1366.  
  1367.  
  1368.  
  1369. ;*-------------------------------------------------------------------*;
  1370. ;* Handler of process errors                                         *;
  1371. ;*-------------------------------------------------------------------*;
  1372.  
  1373. memory_error      proc    near
  1374.                   assume  cs:cseg,ds:cseg,es:cseg,ss:cseg
  1375.                   push    ds
  1376.                   push    ax
  1377.  
  1378.                   mov     ax,cs
  1379.                   mov     ds,ax
  1380.  
  1381.                   pop     ax
  1382.  
  1383.                   cmp     ax,01h
  1384.                   je      err_mem_01h
  1385.                   cmp     ax,02h
  1386.                   je      err_mem_02h
  1387.                   cmp     ax,05h
  1388.                   je      err_mem_05h
  1389.                   cmp     ax,10
  1390.                   je      err_mem_10h
  1391.                   cmp     ax,11
  1392.                   je      err_mem_11h
  1393.                   cmp     ax,07h
  1394.                   je      err_mem_07h
  1395.                   cmp     ax,08h
  1396.                   je      err_mem_08h
  1397.                   cmp     ax,09h
  1398.                   je      err_mem_09h
  1399.                   cmp     ax,0ffh
  1400.                   je      err_mem_ffh
  1401. err_mem_oth:
  1402.                   mov     dx,offset merrot
  1403.                   call    print
  1404.                   jmp     end_memory
  1405.  
  1406. err_mem_07h:
  1407.                   mov     dx,offset merr07
  1408.                   call    print
  1409.                   jmp     end_memory
  1410. err_mem_01h:
  1411.                   mov     dx,offset merr01
  1412.                   call    print
  1413.                   jmp     end_memory
  1414. err_mem_02h:
  1415.                   mov     dx,offset merr02
  1416.                   call    print
  1417.                   jmp     end_memory
  1418. err_mem_05h:
  1419.                   mov     dx,offset merr05
  1420.                   call    print
  1421.                   jmp     end_memory
  1422. err_mem_10h:
  1423.                   mov     dx,offset merr10
  1424.                   call    print
  1425.                   jmp     end_memory
  1426. err_mem_11h:
  1427.                   mov     dx,offset merr11
  1428.                   call    print
  1429.                   jmp     end_memory
  1430.  
  1431. err_mem_08h:
  1432.                   mov     dx,offset merr08
  1433.                   call    print
  1434.                   jmp     end_memory
  1435.  
  1436. err_mem_09h:
  1437.                   mov     dx,offset merr09
  1438.                   call    print
  1439.                   jmp     end_memory
  1440.  
  1441. err_mem_ffh:
  1442.                   mov     dx,offset merrff
  1443.                   call    print
  1444.                   jmp     end_memory
  1445.  
  1446. end_memory:
  1447.                   call    getkey                          ;Version 2.0
  1448.                   pop     ds
  1449.                   ret
  1450. memory_error      endp
  1451.  
  1452. ;*-------------------------------------------------------------------*;
  1453. ;* Routine to convert from binary to ASCII (Hex Format)              *;
  1454. ;*-------------------------------------------------------------------*;
  1455.  
  1456. L0154             proc    near
  1457.  
  1458.                   push    cx
  1459.                   mov     cx,4
  1460.                   mov     ah,0
  1461.                   rol     ax,cl
  1462.                   ror     al,cl
  1463.  
  1464. L015E:            add     al,30h;'0'
  1465.                   cmp     al,39h;'9'
  1466.                   jle     L0166
  1467.                   add     al,7
  1468.  
  1469. L0166:            cmp     ch,0
  1470.                   je      L016D
  1471.                   xchg    al,ah
  1472.                   pop     cx
  1473.                   ret
  1474.  
  1475.  
  1476. L016D:            mov     ch,1
  1477.                   xchg    al,ah
  1478.                   jmp     L015E
  1479.  
  1480. L0154             endp
  1481.  
  1482. ;*-------------------------------------------------------------------*;
  1483. ;* Print String - BIOS based version of Int 21h Fn=09h               *;
  1484. ;*-------------------------------------------------------------------*;
  1485.  
  1486. print             proc    near
  1487.                   assume  cs:cseg,ds:cseg,es:cseg,ss:cseg
  1488.                   push    es
  1489.                   push    ds
  1490.                   push    ax
  1491.                   push    dx
  1492.                   push    si
  1493.                   push    bx
  1494.                   push    cx
  1495.                   mov     ax,dx
  1496.                   mov     si,ax
  1497.                   mov     ax,cs
  1498.                   mov     ds,ax
  1499.  
  1500. print_loop:
  1501.                   cmp     byte ptr cs:[si],"$"
  1502.                   je      eprint
  1503.  
  1504.                   mov     ah,0Fh
  1505.                   Push    si
  1506.                   Int     10h
  1507.                   Pop     si
  1508.  
  1509.                   mov     bl,00h
  1510.                   mov     al,byte ptr cs:[si]
  1511.                   mov     ah,0eh
  1512.  
  1513.                   Push    si
  1514.                   Int     10h
  1515.                   Pop     si
  1516.  
  1517.                   inc     si
  1518.  
  1519.                   jmp     print_loop
  1520. eprint:
  1521.                   pop     cx
  1522.                   pop     bx
  1523.                   pop     si
  1524.                   pop     dx
  1525.                   pop     ax
  1526.                   pop     ds
  1527.                   pop     es
  1528.                   ret
  1529. print             endp
  1530.  
  1531.  
  1532. ;*-------------------------------------------------------------------*;
  1533. ;* Main Initialization code                                          *;
  1534. ;*-------------------------------------------------------------------*;
  1535.  
  1536. initialize        proc    near
  1537.                   assume  cs:cseg,ds:cseg,es:nothing,ss:cseg
  1538.  
  1539. ;*--- Set addresability & Display Copyright notice
  1540.  
  1541.                   mov     ax,cs
  1542.                   mov     ds,ax
  1543.                   mov     es,ax
  1544.  
  1545.                   mov     dx,offset copyright
  1546.                   call    print
  1547.  
  1548. ;*--- Check if DOS version is greater than 2.00
  1549.  
  1550.                   push    es
  1551.                   push    ds
  1552.                   mov     ah,30h
  1553.                   Int     21h
  1554.  
  1555.                   cmp     al,02h
  1556.                   jge     next_init
  1557.  
  1558. ;*--- No, message error and terminate
  1559.  
  1560.                   mov     load_flag,0
  1561.                   mov     dx,offset wrong_dos
  1562.                   call    print
  1563.                   pop     ds
  1564.                   pop     es
  1565.                   jmp     no_load
  1566.  
  1567. next_init:
  1568.                   pop     ds
  1569.                   pop     es
  1570.                   mov     word ptr [main+0],0
  1571.                   mov     word ptr [main+2],0
  1572.  
  1573. ;*--- Search for copies of itself on DOS memory chain
  1574.  
  1575.                   xor     bx,bx
  1576.                   mov     ax,cs
  1577. next_para:
  1578.                   inc     bx
  1579.                   cmp     ax,bx
  1580.                   mov     es,bx
  1581.                   je      end_search
  1582.                   mov     si,offset id
  1583.                   mov     di,si
  1584.                   mov     cx,id_len
  1585.                   rep     cmpsb
  1586.                   or      cx,cx
  1587.                   jnz     next_para
  1588.  
  1589. ;*--- Another copy was founded, send message and prevent to load again
  1590. ;*--- also, the segment in wich the previous copy was founded is saved
  1591.  
  1592.                   mov     load_flag,0
  1593.                   mov     ax,es
  1594.                   mov     curr_segm,ax
  1595.  
  1596.                   mov     dx,offset yet_loaded
  1597.                   call    print
  1598.                   jmp     get_parm
  1599.  
  1600. end_search:
  1601.  
  1602. ;*--- No another copy can be founded, prosecute installation
  1603.  
  1604.                   mov     load_flag,1
  1605.  
  1606. ;*--- In ES is stored the current CS segment , save it
  1607.  
  1608.                   mov     ax,es
  1609.                   mov     curr_segm,ax
  1610.  
  1611. ;*--- Now command parameters are inspected
  1612.  
  1613.  
  1614. get_parm:
  1615.  
  1616. ;*--- Point to first character of parameter area in the PSP
  1617.  
  1618.                   mov     si,81h
  1619.                   push    cs
  1620.                   pop     ds
  1621.  
  1622. ;*--- Throw away if blank
  1623.  
  1624. parse:
  1625.                   cmp     ds:byte ptr [si],32
  1626.                   jne     parse1
  1627.                   inc     si
  1628.                   jmp     parse
  1629.  
  1630. ;*--- If first non-blank is carriage return the command area is empty
  1631. ;*--- Load with default memory size of 4096 paragraphs
  1632.  
  1633. parse1:
  1634.                   cmp     ds:byte ptr [si],cr
  1635.                   jne     parseus
  1636.                   jmp     locate_com
  1637.  
  1638. ;*--- First non-blank is "/" or is an error
  1639.  
  1640. parseus:
  1641.  
  1642.                   cmp     ds:byte ptr [si],2Fh
  1643.                   je      parnum
  1644.                   jmp     error_parm
  1645.  
  1646. ;*--- Try to convert parameter from ASCII to binary
  1647.  
  1648. parnum:
  1649.                   push    si
  1650.                   inc     si
  1651.                   mov     ax,si
  1652.                   mov     dx,ax
  1653.                   mov     ax,cs
  1654.                   mov     ds,ax
  1655.                   call    cnvd2h
  1656.                   cmp     ax,0000h
  1657.                   je      parsest
  1658.  
  1659. ;*--- Sucefull conversion, the number is stored as a requested memory size
  1660.  
  1661.                   lea     di,size_area
  1662.                   mov     word ptr cs:[di],ax
  1663.                   pop     si
  1664.  
  1665. ;*--- If there are another copy on memory try to change it workspace size
  1666.  
  1667.                   cmp     load_flag,1
  1668.                   jne     parsesi
  1669.  
  1670.                   jmp     locate_com
  1671.  
  1672. ;*--- First check if it is inactive, this would ensure that there are no
  1673. ;*--- workspace allocated to it
  1674.  
  1675. parsesi:
  1676.                   mov     ax,curr_segm
  1677.                   mov     es,ax
  1678.                   cmp     es:dormant,01h
  1679.  
  1680.                   je      parses1
  1681.                   jmp     locate_com
  1682. parses1:
  1683.  
  1684. ;*--- The newest size area is stamped on the resident copy and the control
  1685. ;*--- is transfered to the regular activation procedure
  1686.  
  1687.                   mov     ax,word ptr cs:size_area
  1688.                   mov     word ptr es:size_area,ax
  1689.                   jmp     activation
  1690.  
  1691. ;*--- The parameter is in valid format but it is not a number
  1692. ;*--- check if is one of /H,/U,/I,/E,/A or /?
  1693.  
  1694. parsest:
  1695.  
  1696. ;*--- Restore SI register just to clean up the stack
  1697.  
  1698.                   pop     si
  1699.  
  1700. parse0:
  1701.  
  1702. ;*--- Force UpperCase
  1703.  
  1704.                   mov     ah,ds:byte ptr [si+1]
  1705.                   mov     ar,ah
  1706.                   and     ds:byte ptr [si+1],0DFh
  1707.  
  1708. ;*--- Is /E , Then is an External Swap indication
  1709.  
  1710.                   cmp     ds:word ptr [si],452Fh
  1711.                   jne     parse1b
  1712.                   jmp     set_ext
  1713.  
  1714. ;*--- Is /H , Then is a Huge Mode indication
  1715.  
  1716. parse1b:
  1717.                   cmp     ds:word ptr [si],482Fh
  1718.                   jne     parse1a
  1719.                   jmp     set_huge
  1720.  
  1721. ;*--- Is /A , Then is an Activation Request
  1722.  
  1723. parse1a:
  1724.                   cmp     ds:word ptr [si],412Fh
  1725.                   jne     parse2
  1726.                   jmp     activation
  1727.  
  1728. ;*--- Is /U , Then is an UnInstall request
  1729.  
  1730. parse2:
  1731.                   cmp     ds:word ptr [si],552Fh
  1732.                   jne     parse3
  1733.                   jmp     uninstall
  1734.  
  1735. ;*--- Is /I , Then is an Inactivation request
  1736.  
  1737. parse3:
  1738.                   cmp     ds:word ptr [si],492Fh
  1739.                   jne     parse4
  1740.                   jmp     inactivation
  1741.  
  1742. ;*--- Is /? , Then display a help text
  1743.  
  1744. parse4:
  1745.                   mov     ah,ar
  1746.                   mov     byte ptr ds:[si+1],ah
  1747.                   cmp     ds:word ptr [si],3F2Fh
  1748.                   jne     parse5
  1749.                   jmp     help
  1750.  
  1751. ;*--- Is /C , Then search for filename
  1752. parse5:
  1753.                   and     ds:byte ptr [si+1],0DFh
  1754.                   cmp     ds:word ptr [si],432Fh
  1755.                   je      user_spec
  1756.  
  1757.                   mov     dx,offset invalid_parm
  1758.                   call    print
  1759.                   jmp     locate_com
  1760.  
  1761. ;*--- Establish huge mode (automatically set external swap mode)
  1762.  
  1763. set_huge:
  1764.                   mov     byte ptr es:huge_mode,01h
  1765.  
  1766. ;*--- Print message telling about the huge selection
  1767.  
  1768.                   mov     dx,offset huge_mode_msg
  1769.                   call    print
  1770.  
  1771. ;*--- Save the position on the command line
  1772.  
  1773.                   push    si
  1774.  
  1775. ;*--- Put a message telling about the Huge mode in the wakeup message
  1776.  
  1777.                   lea     di,es:type_msg
  1778.                   lea     si,es:huge_msg
  1779.                   mov     al,04h
  1780. set_hugea:
  1781.                   mov     ah,byte ptr ds:[si]
  1782.                   mov     byte ptr ds:[di],ah
  1783.                   inc     si
  1784.                   inc     di
  1785.                   dec     al
  1786.  
  1787.                   cmp     al,00h
  1788.                   jne     set_hugea
  1789.  
  1790. ;*--- Restore the position on the command line
  1791.  
  1792.                   pop     si
  1793.  
  1794.                   jmp     set_ext
  1795.  
  1796.  
  1797. ;*--- get address of dos_command buffer & reset counter
  1798.  
  1799. user_spec:
  1800.                   mov     di,offset dos_command
  1801.                   mov     byte ptr es:[di],00h
  1802.                   push    di
  1803.                   xor     ah,ah
  1804.                   inc     di
  1805.  
  1806. ;*--- Transfer command line till the CR
  1807.  
  1808. user_01:
  1809.                   cmp     byte ptr [si],cr
  1810.                   je      end_user
  1811.                   mov     al,byte ptr [si]
  1812.                   mov     es:byte ptr [di],al
  1813.                   inc     si
  1814.                   inc     di
  1815.                   inc     ah
  1816.                   cmp     byte ptr [si],"/"
  1817.                   je      end_user
  1818.                   jmp     user_01
  1819.  
  1820. ;*--- Store correct values on flag,counter
  1821.  
  1822. end_user:
  1823.                   mov     es:byte ptr [di],cr
  1824.                   pop     di
  1825.                   mov     es:byte ptr [di],ah
  1826.                   mov     ah,01h
  1827.                   mov     es:byte ptr command_flag,ah
  1828.                   mov     dx,offset user_file
  1829.                   call    print
  1830.                   jmp     parse
  1831.  
  1832. ;*--- Display help text and exit without being resident
  1833.  
  1834. help:
  1835.                   mov     dx,offset flash_help
  1836.                   call    print
  1837.                   mov     load_flag,0
  1838.                   jmp     no_load
  1839.  
  1840. ;*--- Invalid parameter is given, display error and exit
  1841.  
  1842. error_parm:
  1843.                   mov     dx,offset invalid_parm
  1844.                   call    print
  1845.                   mov     load_flag,0
  1846.                   jmp     no_load
  1847.  
  1848. ;*--- Set external swap flag
  1849.  
  1850. set_ext:
  1851.  
  1852.                   mov     ax,curr_segm
  1853.                   mov     es,ax
  1854.                   mov     byte ptr es:buffer_type,"E"
  1855.                   mov     dx,offset exter_stor
  1856.                   call    print
  1857.  
  1858.                   inc     si
  1859.                   inc     si
  1860.  
  1861.                   push    si
  1862.                   push    di
  1863.                   push    bx
  1864.  
  1865. ;*--- If huge mode is active the message was already moved
  1866.  
  1867.                   cmp     byte ptr es:huge_mode,01h
  1868.                   jz      set_extb
  1869.  
  1870. ;*--- Transfer the regular disk message
  1871.  
  1872.                   lea     di,es:type_msg
  1873.                   lea     si,es:disk_msg
  1874.                   mov     al,04h
  1875. set_exta:
  1876.                   mov     ah,byte ptr ds:[si]
  1877.                   mov     byte ptr ds:[di],ah
  1878.                   inc     si
  1879.                   inc     di
  1880.                   dec     al
  1881.  
  1882.                   cmp     al,00h
  1883.                   jne     set_exta
  1884.  
  1885. set_extb:
  1886.  
  1887. ;*--- When the external mode is selected additional provisions must be taken
  1888. ;*--- to ensure that any code in the swapped part IS NOT part of an
  1889. ;*--- interruption.
  1890. ;*--- The safest way is to save the interrupt status in this moment and
  1891. ;*--- swap back and forth this one when Flashdos is invoked.
  1892.  
  1893.                   push    es
  1894.                   mov     ax,0000h
  1895.                   mov     es,ax
  1896.  
  1897.                   mov     si,0000h
  1898.                   lea     di,ds:old_int_area
  1899.                   mov     bx,1024
  1900.  
  1901. reintnew:
  1902.                   mov     ah,byte ptr es:[si]
  1903.                   mov     byte ptr ds:[di],ah
  1904.                   inc     di
  1905.                   inc     si
  1906.                   dec     bx
  1907.  
  1908.                   mov     ax,bx
  1909.                   cmp     ax,0000h
  1910.                   jne     reintnew
  1911.  
  1912.                   pop     es
  1913.  
  1914.                   pop     bx
  1915.                   pop     di
  1916.                   pop     si
  1917.  
  1918.                   jmp     parse
  1919.  
  1920. ;*--- Activation request
  1921.  
  1922. activation:
  1923.                   cmp     load_flag,0
  1924.                   je      activ01
  1925.  
  1926. ;*--- Cann't activate if it is not in memory
  1927.  
  1928.                   mov     dx,offset no_loaded
  1929.                   call    print
  1930.                   mov     load_flag,0
  1931.                   jmp     no_load
  1932.  
  1933. ;*--- See if it is yet active
  1934. activ01:
  1935.                   mov     ax,curr_segm
  1936.                   mov     es,ax
  1937.  
  1938.                   cmp     byte ptr es:dormant,0
  1939.                   jne     activ02
  1940.  
  1941. ;*--- Is already active, you cann't active it again
  1942.  
  1943.                   mov     dx,offset yet_active
  1944.                   call    print
  1945.                   mov     load_flag,0
  1946.                   jmp     no_load
  1947.  
  1948. ;*--- The program is resident and inactive, so active it
  1949. ;*--- Program Owns all the memory, shrink it to a minimun if internal swap
  1950.  
  1951. activ02:
  1952.  
  1953.                   cmp     es:buffer_type,"E"
  1954.                   je      activ05
  1955.  
  1956.                   mov     ax,cs
  1957.                   mov     bx,prog_len
  1958.                   add     bx,video_len
  1959.                   push    es
  1960.                   mov     es,ax
  1961.                   mov     ah,4Ah
  1962.                   int     21h
  1963.                   pop     es
  1964.                   jnc     activ03
  1965.  
  1966.                   call    memory_error
  1967.                   mov     load_flag,1
  1968.                   jmp     no_load
  1969.  
  1970. activ03:
  1971.  
  1972. ;*--- Get workspace area, save the returned pointer for future use
  1973.  
  1974.                   mov     ax,cs
  1975.                   mov     ds,ax
  1976.                   mov     bx,es:size_area
  1977.                   mov     ah,48h
  1978.                   push    es
  1979.                   Int     21h
  1980.                   pop     es
  1981.                   jnc     activ04
  1982.  
  1983.                   call    memory_error
  1984.                   mov     load_flag,1
  1985.                   jmp     no_load
  1986.  
  1987. activ04:
  1988.  
  1989. ;*--- The work memory was claimed suceffully store pointer
  1990.  
  1991.                   mov     word ptr es:ptr_area,ax
  1992.  
  1993. ;*--- The memory claimed is under the property of the running FlashDOS and
  1994. ;*--- not of the resident portion, some DOS memory block adjusting is in place
  1995.  
  1996.                   push    es
  1997.                   push    ds
  1998.  
  1999.                   mov     word ptr es:ptr_area,ax
  2000.                   dec     ax
  2001.                   mov     ds,ax
  2002.  
  2003.                   assume  ds:mem
  2004.  
  2005.                   cmp     ds:memtype,"M"
  2006.                   jne     act_mem_err
  2007.  
  2008.                   mov     ax,es
  2009.                   mov     ds:memid,ax
  2010.                   pop     ds
  2011.                   pop     es
  2012.  
  2013. ;*--- Restablish addresability
  2014.  
  2015.                   assume  cs:cseg,ds:cseg,es:cseg,ss:cseg
  2016.  
  2017. activ05:
  2018.  
  2019.                   mov     ax,cs
  2020.                   mov     ds,ax
  2021.  
  2022. ;*--- Change active flag to active
  2023.  
  2024.                   mov     byte ptr es:dormant,0
  2025.  
  2026. ;*--- Send message and exit
  2027.  
  2028.                   mov     dx,offset now_active
  2029.                   call    print
  2030.                   mov     load_flag,0
  2031.                   jmp     no_load
  2032.  
  2033. ;*--- Display memory management problem and exit
  2034.  
  2035. act_mem_err:
  2036.                   mov     ax,0ffh
  2037.                   call    memory_error
  2038.                   mov     load_flag,0
  2039.                   jmp     no_load
  2040.  
  2041. ;*--- Inactivation Request
  2042.  
  2043. inactivation:
  2044.                   call    set_inactive
  2045.                   jmp     no_load
  2046.  
  2047. ;*--- UnInstall Request
  2048.  
  2049. Uninstall:
  2050.                   cmp     load_flag,0
  2051.                   je      unins01
  2052.  
  2053. ;*--- Cann't uninstall if it is not in memory
  2054.  
  2055.                   mov     dx,offset no_loaded
  2056.                   call    print
  2057.                   mov     load_flag,0
  2058.                   jmp     no_load
  2059.  
  2060. ;*--- See if it is active or inactive
  2061.  
  2062. unins01:
  2063.                   mov     ax,curr_segm
  2064.                   mov     es,ax
  2065.  
  2066.                   cmp     byte ptr es:dormant,0
  2067.  
  2068.                   jne     unins02
  2069.  
  2070. ;*--- Cann't uninstall if it is not inactive
  2071.  
  2072.                   push    es
  2073.                   call    set_inactive
  2074.                   pop     es
  2075.  
  2076. ;*--- Now, check if all interrupts trapped still pointing to myself
  2077.  
  2078. unins02:
  2079.  
  2080. ;*--- Interrupt 09h (Keyboard) is verified against resident segment
  2081.  
  2082.                   push    es
  2083.                   mov     ah,35h
  2084.                   mov     al,09h
  2085.                   Int     21h
  2086.                   mov     bx,es
  2087.                   pop     es
  2088.                   mov     ax,es
  2089.                   cmp     bx,ax
  2090.                   je      int09_ok
  2091.  
  2092. ;*--- Is different, cann't uninstall
  2093.  
  2094.                   mov     dx,offset wrong_int09
  2095.                   call    print
  2096.                   mov     load_flag,0
  2097.                   jmp     no_load
  2098. int09_ok:
  2099.  
  2100. ;*--- Interrupt 13h (BIOS Disk) is verified against resident segment
  2101.  
  2102.                   push    es
  2103.                   mov     ah,35h
  2104.                   mov     al,13h
  2105.                   Int     21h
  2106.                   mov     bx,es
  2107.                   pop     es
  2108.                   mov     ax,es
  2109.                   cmp     bx,ax
  2110.                   je      int13_ok
  2111.  
  2112. ;*--- Is different, cann't uninstall
  2113.  
  2114.                   mov     dx,offset wrong_int13
  2115.                   call    print
  2116.                   mov     load_flag,0
  2117.                   jmp     no_load
  2118. int13_ok:
  2119.  
  2120. ;*--- Interrupt 21h (DOS Function) is verified against resident segment
  2121.  
  2122.                   push    es
  2123.                   mov     ah,35h
  2124.                   mov     al,21h
  2125.                   Int     21h
  2126.                   mov     bx,es
  2127.                   pop     es
  2128.                   mov     ax,es
  2129.                   cmp     bx,ax
  2130.                   je      int21_ok
  2131.  
  2132. ;*--- Is different, cann't uninstall
  2133.  
  2134.                   mov     dx,offset wrong_int21
  2135.                   call    print
  2136.                   mov     load_flag,0
  2137.                   jmp     no_load
  2138. int21_ok:
  2139.  
  2140. ;*--- All trapped interrupts belong to FlashDOS so restore old values
  2141.  
  2142. ;*--- Restore Int09h
  2143.  
  2144.                   push    es
  2145.                   lds     dx,es:old_int_9
  2146.                   mov     ah,25h
  2147.                   mov     al,09h
  2148.                   Int     21h
  2149.                   pop     es
  2150.  
  2151. ;*--- Restore Int13h
  2152.  
  2153.                   push    es
  2154.                   lds     dx,es:old_int_13
  2155.                   mov     ah,25h
  2156.                   mov     al,13h
  2157.                   Int     21h
  2158.                   pop     es
  2159.  
  2160. ;*--- Restore Int21h
  2161.  
  2162.                   push    es
  2163.                   lds     dx,es:old_int_21
  2164.                   mov     ah,25h
  2165.                   mov     al,21h
  2166.                   Int     21h
  2167.                   pop     es
  2168.  
  2169. ;*--- Corrupt the signature, otherwise another try to load FlashDOS would fail
  2170.  
  2171.                   xor     ax,ax
  2172.                   mov     es:id,al
  2173.  
  2174. ;*--- Now resident FlashDOS is a dead memory zone, release environment
  2175.  
  2176.                   push    es
  2177.                   mov     ax,word ptr es:2Ch
  2178.                   mov     es,ax
  2179.                   mov     ah,49h
  2180.                   Int     21h
  2181.                   pop     es
  2182.  
  2183. ;*--- Release resident program itself
  2184.  
  2185.                   push    es
  2186.                   mov     ah,49h
  2187.                   Int     21h
  2188.                   pop     es
  2189.  
  2190. ;*--- Uninstallation complete, display a message
  2191.  
  2192.                   mov     dx,offset now_uninstall
  2193.                   call    print
  2194.                   mov     load_flag,0
  2195.                   jmp     no_load
  2196.  
  2197. ;*--- Get the current COMMAND.COM path from the Environment Block
  2198.  
  2199. locate_com:
  2200.  
  2201. ;*--- Check if there are another copy in memory
  2202.  
  2203.                   cmp     load_flag,0
  2204.                   jne     loc_com
  2205.                   jmp     no_load
  2206.  
  2207. ;*--- Inspect environment area
  2208.  
  2209. loc_com:
  2210.                   push    es
  2211.                   mov     ax,word ptr cs:2Ch
  2212.                   mov     es,ax
  2213.                   mov     ax,offset env_var
  2214.                   mov     si,ax
  2215.                   mov     cx,env_var_len
  2216.  
  2217.                   call    Get_Env_Str
  2218.  
  2219.  
  2220.                   cmp     al,00h
  2221.                   jne     no_comm_found
  2222.                   mov     ax,offset comspec_path
  2223.                   mov     si,ax
  2224.  
  2225. locate_loop:
  2226.  
  2227.                   mov     al,byte ptr es:[di]
  2228.                   cmp     al,00h
  2229.                   je      end_locate
  2230.  
  2231.                   mov     byte ptr cs:[si],al
  2232.                   inc     si
  2233.                   inc     di
  2234.                   jmp     locate_loop
  2235.  
  2236.  
  2237. end_locate:
  2238.  
  2239.                   mov     byte ptr cs:[si],al
  2240.  
  2241. ;*--- No 'COMSPEC'  variable can be found in the environment
  2242.  
  2243. no_comm_found:
  2244.  
  2245.                   pop     es
  2246.  
  2247. continue:
  2248.  
  2249. ;*--- Program Owns all the memory, shrink it to a minimun
  2250.  
  2251.  
  2252.                   mov     ax,cs
  2253.                   mov     es,ax
  2254.                   mov     bx,prog_len
  2255.                   add     bx,video_len
  2256.                   mov     ah,4Ah
  2257.                   int     21h
  2258.                   jnc     cont01
  2259.  
  2260.                   call    memory_error
  2261.                   mov     load_flag,1
  2262.                   jmp     no_load
  2263.  
  2264. cont01:
  2265.  
  2266. ;*--- If internal get workspace area, save the returned pointer for future use
  2267.  
  2268.                   cmp     buffer_type,"E"
  2269.                   je      cont02b
  2270.  
  2271.                   mov     ax,cs
  2272.                   mov     ds,ax
  2273.                   mov     bx,size_area
  2274.                   mov     ah,48h
  2275.                   Int     21h
  2276.                   jnc     cont02
  2277.  
  2278.                   call    memory_error
  2279.                   mov     load_flag,1
  2280.                   jmp     no_load
  2281.  
  2282. cont02:
  2283.                   mov     word ptr cs:ptr_area,ax
  2284.  
  2285. ;*--- Get the DOS Critical Flag Address (Undocumented)
  2286.  
  2287. cont02b:
  2288.  
  2289.                   mov     ah,34h
  2290.                   int     21h
  2291.                   mov     word ptr dos_flag[0],bx
  2292.                   mov     word ptr dos_flag[2],es
  2293.  
  2294. ;*--- Trap Int 09h, 10h and 21h
  2295.  
  2296.                   push    ds
  2297.                   pop     es
  2298.  
  2299.                   mov     al,9
  2300.                   mov     di,offset old_int_9
  2301.                   mov     dx,offset int_9
  2302.                   call    set_int
  2303.  
  2304.                   mov     al,13h
  2305.                   mov     di,offset old_int_13
  2306.                   mov     dx,offset int_13
  2307.                   call    set_int
  2308.  
  2309.                   mov     al,21h
  2310.                   mov     di,offset old_int_21
  2311.                   mov     dx,offset int_21
  2312.                   call    set_int
  2313.  
  2314. ;*--- Main initializacion job done, so print message
  2315.  
  2316.                   mov     dx,offset loaded_ok
  2317.                   call    print
  2318.  
  2319. ;*--- Get pointer to workspace and convert binary to ASCII, print it.
  2320.  
  2321.                   cmp     buffer_type,"E"
  2322.                   je      cont03a
  2323.  
  2324.                   mov     ax,word ptr cs:ptr_area
  2325.                   call    L0154
  2326.                   mov     MSBH,ah
  2327.                   mov     MSBL,al
  2328.                   mov     ax,ptr_area
  2329.                   mov     al,ah
  2330.                   call    L0154
  2331.                   mov     LSBH,ah
  2332.                   mov     LSBL,al
  2333.  
  2334.                   mov     dx,offset mem_ptr
  2335.                   call    print
  2336.  
  2337. ;*--- Get workspace size in paragraphs and convert binary to ASCII, print it.
  2338.  
  2339. cont03a:
  2340. ;*--- If it is on huge mode the workspace size doesn't matter.
  2341.  
  2342.                   cmp     byte ptr cs:huge_mode,01h
  2343.                   jz      tsr_pgm
  2344.  
  2345.                   mov     ax,word ptr cs:size_area
  2346.                   call    L0154
  2347.                   mov     MMSBH,ah
  2348.                   mov     MMSBL,al
  2349.                   mov     ax,size_area
  2350.                   mov     al,ah
  2351.                   call    L0154
  2352.                   mov     MLSBH,ah
  2353.                   mov     MLSBL,al
  2354.  
  2355.                   mov     dx,offset mem_size
  2356.                   call    print
  2357.  
  2358.  
  2359. ;*--- Terminate and Stay Resident
  2360.  
  2361. tsr_pgm:
  2362.                   mov     dx,prog_len
  2363.                   add     dx,video_len
  2364.                   mov     ax,3100h
  2365.                   int     21h
  2366.  
  2367. ;*--- Procedure to avoid to keep as a TSR
  2368.  
  2369. no_load:
  2370.                   mov     dx,offset not_loaded
  2371.                   call    print
  2372.  
  2373.                   mov     al,04h
  2374.                   mov     ah,4ch
  2375.                   Int     21h
  2376.  
  2377. initialize        endp
  2378.  
  2379. ;*-------------------------------------------------------------------*;
  2380. ;* Routine to Trap current interrupt and set the own one             *;
  2381. ;*-------------------------------------------------------------------*;
  2382.  
  2383. set_int           proc    near
  2384.                   assume  cs:cseg,ds:cseg,es:cseg,ss:cseg
  2385.                   push    ax
  2386.                   mov     ah,35h
  2387.                   int     21h
  2388.                   mov     word ptr [di+0],bx
  2389.                   mov     word ptr [di+2],es
  2390.                   pop     ax
  2391.                   mov     ah,25h
  2392.                   int     21h
  2393.  
  2394.                   ret
  2395. set_int           endp
  2396.  
  2397. ;*-------------------------------------------------------------------*;
  2398. ;*GET_ENV_STR procedure to find a string in the environment          *;
  2399. ;*Input:  ES pointer to environment                                  *;
  2400. ;*        SI pointer to variable to find plus equals sign            *;
  2401. ;*        CX length of variable including equals sign                *;
  2402. ;*Output: DI pointer to start of value of variable, if AL=0          *;
  2403. ;*        AL 0 if string found, 1 if not                             *;
  2404. ;*        ES,SI,CX unchanged                                         *;
  2405. ;*Borrowed from ENVPTR Package by Jeff Urs from PCTOOLS              *;
  2406. ;*-------------------------------------------------------------------*;
  2407.  
  2408. Get_Env_Str:      Sub     DI,DI
  2409.                   Cld
  2410.  
  2411. End_Check:        Cmp     Byte Ptr ES:[DI],00
  2412.                   Jne     Check_Str
  2413.                   Mov     AL,1
  2414.                   Jmp     Short Get_Env_End
  2415.  
  2416. Check_Str:        Push    SI
  2417.                   Push    CX
  2418.                   Repe    Cmpsb
  2419.                   Pop     CX
  2420.                   Pop     SI
  2421.                   Jne     Next_Str
  2422.                   Xor     AL,AL
  2423.                   Jmp     Short Get_Env_End
  2424.  
  2425. Next_Str:         Xor     AL,AL
  2426.                   Push    CX
  2427.                   Mov     CX,8000H
  2428.                   Repne   Scasb
  2429.                   Pop     CX
  2430.                   Jmp     End_Check
  2431. ;
  2432. Get_Env_End:      Ret
  2433.  
  2434. ;*-------------------------------------------------------------------*;
  2435. ;*    CNVD2H:  This routine will convert a decimal string into a hex-*;
  2436. ;*    adecimal word value.  The user passes a pointer to a string    *;
  2437. ;*    containing a value between -32768 and 65535.                   *;
  2438. ;*                                                                   *;
  2439. ;*    INPUT: DS:DX - number string to convert                        *;
  2440. ;*    OUTPUT: AX - output value                                      *;
  2441. ;*                                                                   *;
  2442. ;*    All registers are preserved except AX.                         *;
  2443. ;*                                                                   *;
  2444. ;*    Written by G. R. Ingalls - 4/29/87                             *;
  2445. ;*-------------------------------------------------------------------*;
  2446.  
  2447. cnvd2h            proc    near
  2448.  
  2449. ;*--- Save Registers
  2450.  
  2451.                   push    bx
  2452.                   push    cx
  2453.                   push    dx
  2454.                   push    es
  2455.                   push    di
  2456.                   push    si
  2457.  
  2458. ;*--- Scan charater string to be converted
  2459.  
  2460.                   mov     si,dx
  2461.                   mov     bl,1
  2462.  
  2463. get_sign:
  2464.  
  2465. ;*--- Check for first non-blank character
  2466.  
  2467.                   lodsb
  2468.                   cmp     al,' '
  2469.                   je      get_sign
  2470.  
  2471. ;*--- If a sign is founded (+ or -) save it
  2472.  
  2473.                   cmp     al,'+'
  2474.                   jne     chk_minus_sign
  2475.                   jmp     got_sign
  2476.  
  2477. chk_minus_sign:
  2478.  
  2479.                   cmp     al,'-'
  2480.                   jne     no_sign
  2481.                   mov     bl,-1
  2482.                   jmp     got_sign
  2483.  
  2484. no_sign:
  2485.  
  2486. ;*--- Restore character pointer
  2487.  
  2488.                   dec     si
  2489.  
  2490. got_sign:
  2491.                   push    bx
  2492.  
  2493. ;*--- For each numeric character add it to the result, stop at first non num
  2494. ;*--- Clear CX to store results
  2495.  
  2496.                   xor     cx,cx
  2497.  
  2498. next_character:
  2499.  
  2500.                   lodsb
  2501.  
  2502. ;*--- Check if it is numeric value
  2503.  
  2504.                   cmp     al,'0'
  2505.                   jb      not_numeric
  2506.                   cmp     al,'9'
  2507.                   ja      not_numeric
  2508.  
  2509. ;*--- Convert to binary
  2510.  
  2511.                   sub     al,'0'
  2512.                   cbw
  2513.                   xchg    ax,cx
  2514.                   mov     bx,10
  2515.                   mul     bx
  2516.  
  2517. ;*--- Add to counter
  2518.  
  2519.                   add     ax,cx
  2520.                   xchg    ax,cx
  2521.                   jmp     next_character
  2522.  
  2523. not_numeric:
  2524.  
  2525. ;*--- Set the proper sign                                                 ;
  2526.  
  2527.                   pop     bx
  2528.                   cmp     bl,-1
  2529.                   jne     not_negative
  2530.                   neg     cx
  2531.  
  2532. not_negative:
  2533.  
  2534.  
  2535. ;*--- Put result in AX and exit                                           ;
  2536.  
  2537.                   mov     ax,cx
  2538.  
  2539.                   pop     si
  2540.                   pop     di
  2541.                   pop     es
  2542.                   pop     dx
  2543.                   pop     cx
  2544.                   pop     bx
  2545.                   ret
  2546.  
  2547. cnvd2h            endp
  2548.  
  2549.  
  2550. ;*-------------------------------------------------------------------*;
  2551. ;* Proc to inactivate the program, shared by inactive and uninstall  *;
  2552. ;*-------------------------------------------------------------------*;
  2553.  
  2554. set_inactive      proc    near
  2555.  
  2556.                   cmp     load_flag,0
  2557.                   je      inact01
  2558.  
  2559. ;*--- Cann't inactivate if it is not in memory
  2560.  
  2561.                   mov     dx,offset no_loaded
  2562.                   call    print
  2563.                   mov     load_flag,0
  2564.                   ret
  2565.  
  2566. ;*--- See if it is yet inactive
  2567.  
  2568. Inact01:
  2569.                   mov     ax,curr_segm
  2570.                   mov     es,ax
  2571.  
  2572.                   cmp     byte ptr es:dormant,1
  2573.                   jne     Inact02
  2574.  
  2575. ;*--- Is already inactive, you cann't inactive it again
  2576.  
  2577.                   mov     dx,offset yet_inactive
  2578.                   call    print
  2579.                   mov     load_flag,0
  2580.                   ret
  2581.  
  2582. ;*--- Is resident and active, inactive and freed memory buffer
  2583.  
  2584. Inact02:
  2585.                   mov     byte ptr es:dormant,1
  2586.  
  2587. ;*--- If external swap is required don't mess with the memory
  2588.  
  2589.                   cmp     es:buffer_type,"E"
  2590.                   je      inact03
  2591.  
  2592. ;*--- Get pointer to workspace area
  2593.  
  2594.                   mov     ax,word ptr es:ptr_area
  2595.  
  2596. ;*--- Freed up reserved workspace area
  2597.  
  2598.                   mov     es,ax
  2599.                   mov     ah,49h
  2600.                   Int     21h
  2601.  
  2602. ;*--- OK, display message and end
  2603.  
  2604.                   jc      cannt_inactive
  2605.  
  2606. inact03:
  2607.  
  2608.                   mov     dx,offset now_inactive
  2609.                   call    print
  2610.                   mov     load_flag,0
  2611.                   ret
  2612.  
  2613. ;*--- Something wrongs occurs, FlashDOS cann't free up the memory
  2614.  
  2615. cannt_inactive:
  2616.  
  2617.                   call    memory_error
  2618.                   mov     byte ptr es:dormant,0
  2619.                   mov     load_flag,0
  2620.                   ret
  2621.  
  2622. set_inactive      endp
  2623.  
  2624. ;*-------------------------------------------------------------------*;
  2625. ;* Messages and variables used during initialization process only    *;
  2626. ;*-------------------------------------------------------------------*;
  2627.  
  2628. curr_segm         dw      ?
  2629. not_loaded        db      cr,lf
  2630.                   db      "FlashDOS: Not Loaded",cr,lf,"$"
  2631. loaded_ok         db      cr,lf
  2632.                   db      "FlashDOS: Loaded sucefully",cr,lf,"$"
  2633. yet_loaded        db      cr,lf
  2634.                   db      "FlashDOS: Already Loaded",cr,lf,"$"
  2635. yet_active        db      cr,lf
  2636.                   db      "FlashDOS: Already Active",cr,lf,"$"
  2637. yet_inactive      db      cr,lf
  2638.                   db      "FlashDOS: Already Inactive",cr,lf,"$"
  2639. now_active        db      cr,lf
  2640.                   db      "FlashDOS: Now Active",cr,lf,"$"
  2641. exter_stor        db      cr,lf
  2642.                   db      "FlashDOS: External Storage Selected",cr,lf,"$"
  2643. now_uninstall     db      cr,lf
  2644.                   db      "FlashDOS: Uninstalled sucefully",cr,lf,"$"
  2645. mem_ptr           db      cr,lf,"FlashDOS: Memory area allocated at "
  2646. LSBH              db      "0"
  2647. LSBL              db      "0"
  2648. MSBH              db      "0"
  2649. MSBL              db      "0"
  2650.                   db      ":0000h",cr,lf,"$"
  2651.  
  2652. mem_size          db      cr,lf,"FlashDOS: Memory size "
  2653. MLSBH             db      "0"
  2654. MLSBL             db      "0"
  2655. MMSBH             db      "0"
  2656. MMSBL             db      "0"
  2657.                   db      "h Paragraphs",cr,lf,"$"
  2658. copyright         db      cr,lf
  2659.                   db      "╔══════════════════════════╗",cr,lf
  2660.                   db      "║FlashDOS V2.1 by P.E.Colla║",cr,lf
  2661.                   db      "║  IBM Internal Use Only   ║",cr,lf
  2662.                   db      "║        DOS Switch        ║",cr,lf
  2663.                   db      "║      COLLA @ MARVM1      ║",cr,lf
  2664.                   db      "║Press Alt-Backspace to Pop║",cr,lf
  2665.                   db      "╚══════════════════════════╝",cr,lf
  2666.                   db      "$"
  2667. huge_mode_msg     db      cr,lf
  2668.                   db      "FlashDOS: Huge Mode Selected",cr,lf,"$"
  2669. user_file         db      cr,lf
  2670.                   db      "FlashDOS: User File Defined",cr,lf,"$"
  2671. wrong_dos         db      cr,lf
  2672.                   db      "FlashDOS: Incorrect DOS Level",cr,lf,"$"
  2673. wrong_int09       db      cr,lf
  2674.                   db      "FlashDOS: Unable to restore Int 09h.",cr,lf,"$"
  2675. wrong_int13       db      cr,lf
  2676.                   db      "FlashDOS: Unable to restore Int 13h.",cr,lf,"$"
  2677. wrong_int21       db      cr,lf
  2678.                   db      "FlashDOS: Unable to restore Int 21h.",cr,lf,"$"
  2679. must_inactive     db      cr,lf
  2680.                   db      "FlashDOS: Must be inactive to Uninstall",cr,lf,"$"
  2681. no_loaded         db      cr,lf
  2682.                   db      "FlashDOS: Not previously loaded.",cr,lf,"$"
  2683. invalid_parm      db      cr,lf
  2684.                   db      "FlashDOS: Incorrect parameter, type FlashDOS /?"
  2685.                   db      " for help.",cr,lf,"$"
  2686. flash_help        db      cr,lf
  2687.                   db      "  FlashDOS Version 2.1 by P.E.Colla 1988  ",cr,lf
  2688.                   db      "This program start a secondary DOS command",cr,lf
  2689.                   db      "processor from inside another application.",cr,lf
  2690.                   db      "Using it you can manage a limited kind of ",cr,lf
  2691.                   db      "multitasking. At loading time the user must",cr,lf
  2692.                   db      "specify if memory or disk swap is desired.",cr,lf
  2693.                   db      "To invoke them type:                      ",cr,lf
  2694.                   db      "            FLASHDOS /{Switch}            ",cr,lf
  2695.                   db      "Valid Switches values are:                ",cr,lf
  2696.                   db      "  /?      Help                            ",cr,lf
  2697.                   db      "  /E      Swap to disk                    ",cr,lf
  2698.                   db      "  /I      Inactive Request (Shrink Memory)",cr,lf
  2699.                   db      "  /A      Active Request (Growth memory)  ",cr,lf
  2700.                   db      "  /U      Un-Install (became /I if cann't)",cr,lf
  2701.                   db      "  /H      Active Huge Mode                ",cr,lf
  2702.                   db      "  /C Pgm  Install Program as a TSR        ",cr,lf
  2703.                   db      "  /99999  Size in paragraphs of internal  ",cr,lf
  2704.                   db      "          memory area  (default 64k bytes)",cr,lf
  2705.                   db      "The program will not PopUp when you are on",cr,lf
  2706.                   db      "graphics video mode or at DOS prompt.     ",cr,lf
  2707.                   db      "              COLLA @ MARVM1              ",cr,lf
  2708.                   db      "$"
  2709.  
  2710. ar                db      ?
  2711. free              db      "#"
  2712. cseg              ends
  2713. end               main
  2714.  
  2715.